#include "controller3d.h"
#include "view/perspective_view.h"
#include "fixed_point_camera.h"
#include "first_person_camera.h"

const float Controller3D::localTimer = 100; // mseg

Controller3D::Controller3D(View* view,Model* model)
	: Controller(view,model),dragPos(0,0){
	this->drag=false;
	tickCount=0;

	dynamic_cast<PerspectiveView&>(*view).addCamera(new FirstPersonCamera());
}

Controller3D::~Controller3D(){
}

void Controller3D::display() {
	this->view->display();
}

void Controller3D::mouseMotion(float x ,float y){
	PerspectiveView& pview = dynamic_cast<PerspectiveView&>(*this->view);
	if(drag){
		Point dragDir = dragPos - Point(x,y);

		// Normalizar
		if(fabs(dragDir.x1)>0 && fabs(dragDir.x2)>0)
			dragDir = Point(dragDir.x1/fabs(dragDir.x1),dragDir.x2/fabs(dragDir.x2));
		else if(fabs(dragDir.x1)>0)
			dragDir = Point(dragDir.x1/fabs(dragDir.x1),0);
		else if(fabs(dragDir.x2)>0)
			dragDir = Point(0,dragDir.x2/fabs(dragDir.x2));

		pview.getActiveCamera().rotateLR(-dragDir.x1*1.3f);
		pview.getActiveCamera().rotateUD(-dragDir.x2*1.3f);

		dragPos = Point(x,y);
	}

}

void Controller3D::reshape(float w,float h) {
	this->view->reshape(w,h);
}

void Controller3D::mousePressed(int key,int state,float x ,float y){
	if(key==GLUT_LEFT_BUTTON && state==GLUT_DOWN){
		dragPos = Point(x,y);
		drag=true;
	}
	if(key==GLUT_LEFT_BUTTON && state==GLUT_UP)
		drag=false;
}

void Controller3D::keyboard(unsigned char key,float x ,float y){
	Path& p = static_cast<PerspectiveModel*>(this->model)->getRCModel().getRailPath();
	PerspectiveModel& pmodel = dynamic_cast<PerspectiveModel&>(*this->model);
	PerspectiveView& pview = dynamic_cast<PerspectiveView&>(*this->view);
	Camera& camera = pview.getActiveCamera();
	switch(key){
		case 'w':
			camera.move(-0.90f);
			break;
		case 's':
			camera.move(0.90f);
			break;
		case 'a':
			camera.rotateLR(-1.5f);
			break;
		case 'd':
			camera.rotateLR(1.5f);
			break;
		case 'q':
			camera.rotateUD(1.5f);
			break;
		case 'e':
			camera.rotateUD(-1.5f);
			break;
		case 0x2d: // -
			p.modifyStep(pathId,1);
			break;
		case 0x2b: // +
			p.modifyStep(pathId,-1);
			break;
		case 'i':
			pmodel.getCartModel().setLight(!pmodel.getCartModel().getLightState());
			break;
		case 'c':
			if(pview.getActiveCameraNum()==0)
				pview.setActiveCamera(1);
			else
				pview.setActiveCamera(0);
			break;
		case 'b':
			// Camera Follower
			dynamic_cast<PerspectiveModel&>(*model).getRCModel().calculate();
			Camera& c =	static_cast<PerspectiveView*>(this->view)->getCamera(1);
			pathId = p.createPathIterator(3,true);
			p.addFollowerToPathIterator(pathId,static_cast<IFollower*>(&c));

			// Cart Follower
			pmodel.getCartModel().setPosition(*p.begin());
			p.addFollowerToPathIterator(pathId,static_cast<IFollower*>(&pmodel.getCartModel()));

			break;
	}
}

void Controller3D::notifyViewportLeave(){

}

void Controller3D::timer(int value){
	++tickCount;


	if(tickCount>=localTimer/tickSize){
		Path& p = static_cast<PerspectiveModel*>(this->model)->getRCModel().getRailPath();
		p.stepPathIterator(pathId);
		tickCount=0;
	}
}

